import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;

/*
 * When launched this class will setup a redirection on the
 * emulator and create a proxy on LOCALPORT so that traffic
 * on that port is sent to the emulator.
 * 
 * IMPORTANT: This is a regular Java class.
 */
public class EmuWrapper {
	private static final int ADBPORT = 5554;
	private static final int LOCALPORT = 4444;

	public static void main(String[] args) {
		AndroidEmuWrapper emu = new AndroidEmuWrapper(LOCALPORT, ADBPORT);
	}
}

class AndroidEmuWrapper {	
	private InetAddress adbip;
	private int adbport;
	private int localport;

	public AndroidEmuWrapper(int localport, int adbport){
		this.localport = localport;
		this.adbport = adbport;
		EmulatorRedir();
		STCPPipe();
	}
	
	// Handles the emulator redir
	public void EmulatorRedir(){
		// Initialize variables
		Socket MyClient = null;
	    DataInputStream input = null;
	    PrintStream output = null;
	    // Initialize local ip
		try { adbip = InetAddress.getByName("127.0.0.1"); }
		catch (UnknownHostException e1) { e1.printStackTrace();	}
	    // Setup the socket
	    try { MyClient = new Socket(adbip, adbport); }
	    catch (IOException e) {
	    	System.err.println("ERROR: Make sure the emulator is running");
	    	System.out.println(e); System.exit(1); }
	    // Create the input stream
	    try { input = new DataInputStream(MyClient.getInputStream()); }
	    catch (IOException e) { System.out.println(e); System.exit(1); }
	    catch (NullPointerException e) { e.printStackTrace(); System.exit(1); }
	    // Create the output stream
	    try { output = new PrintStream(MyClient.getOutputStream()); }
	    catch (IOException e) { System.out.println(e); System.exit(1); }
	    catch (NullPointerException e) { e.printStackTrace(); System.exit(1); }

	    // Read console
        String responseLine;
        try {
			while ((responseLine = input.readLine()) != null) {
			    System.out.println("Emulator: " + responseLine);
			    if (responseLine.equals("OK")) {
			    	break;
			    }
			}
			// Write the redir
			String redirection = "redir add udp:"+localport+":"+localport;
			System.out.println("Client: " + redirection);
			output.println(redirection);
			boolean flag = false;
			// Make sure it went okay
			while ((responseLine = input.readLine()) != null) {
			    System.out.println("Emulator: " + responseLine);
			    if (responseLine.equals("OK")) {
			    	System.out.println("Redirection successfull");
			    	break;
			    } else if (responseLine.equals("KO: host port already active, use 'redir del' to remove first")) {
					// Get a list of redirs
					String redirlist = "redir list";
					System.out.println("Client: " + redirlist);
					output.println(redirlist);
					while ((responseLine = input.readLine()) != null) {
					    System.out.println("Emulator: " + responseLine);
					    if (responseLine.equals("OK")) {
					    	flag = true;
					    	break;
					    }
					}
			    } else {
			    	System.err.println("EmuWrapper critical error");
			    	System.exit(1);
			    }
				if (flag) { break; }
			}
        }
        catch (IOException e) { e.printStackTrace(); System.exit(1); }
		catch (NullPointerException e) { e.printStackTrace(); System.exit(1); }
	    
	    // Close down the streams and the socket
	    try {
	    	System.out.println("Closing input/output streams and the socket");
	    	output.close();
	    	input.close();
	    	MyClient.close();
	    }
	    catch (IOException e) { System.out.println(e); }
		catch (NullPointerException e) { e.printStackTrace(); }
	}

	// Handles the stcppipe part
	public void STCPPipe(){
		InetAddress inetAddress;
		String ip = "";
		try {
			inetAddress = InetAddress.getLocalHost();
			ip = inetAddress.getHostAddress();  
			CommandLine commandLine = CommandLine.parse("src\\stcppipe\\stcppipe.exe");
			commandLine.addArgument("-b");
			commandLine.addArgument(ip);
			commandLine.addArgument("127.0.0.1");
			commandLine.addArgument(Integer.toString(localport));
			commandLine.addArgument(Integer.toString(localport));
			DefaultExecutor executor = new DefaultExecutor();
			executor.setExitValue(1);
			int exitValue = executor.execute(commandLine);
		} catch (ExecuteException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}	
}